<template>
  <div class="snake-game">
    <h1>贪吃蛇游戏</h1>
    <div class="game-controls">
      <div class="game-controls__btn">
        <el-button type="primary" @click="startGame" :disabled="isRunning">开始</el-button>
        <el-button type="warning" @click="pauseGame" :disabled="!isRunning">暂停</el-button>
        <el-button type="danger" @click="resetGame">重置</el-button>
      </div>
      <el-select v-model="speed" placeholder="选择难度" @change="updateSpeed">
        <el-option label="简单" :value="200"></el-option>
        <el-option label="中等" :value="150"></el-option>
        <el-option label="困难" :value="100"></el-option>
      </el-select>
    </div>
    <canvas ref="canvas" width="500" height="500"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';

const canvas = ref(null);
const ctx = ref(null);
const isRunning = ref(false);
const speed = ref(200);
const interval = ref(null);

const snake = ref([{ x: 10, y: 10 }]);
const direction = ref({ x: 1, y: 0 });
const food = ref({ x: 15, y: 15 });

onMounted(() => {
  ctx.value = canvas.value.getContext('2d');
  drawGame();
  window.addEventListener('keydown', handleKeyDown);
});

onBeforeUnmount(() => {
  window.removeEventListener('keydown', handleKeyDown);
});

const startGame = () => {
  isRunning.value = true;
  interval.value = setInterval(updateGame, speed.value);
};

const pauseGame = () => {
  isRunning.value = false;
  clearInterval(interval.value);
};

const resetGame = () => {
  pauseGame();
  snake.value = [{ x: 10, y: 10 }];
  direction.value = { x: 1, y: 0 };
  food.value = generateFood();
  drawGame();
};

const updateSpeed = () => {
  if (isRunning.value) {
    clearInterval(interval.value);
    interval.value = setInterval(updateGame, speed.value);
  }
};

const updateGame = () => {
  const head = { x: snake.value[0].x + direction.value.x, y: snake.value[0].y + direction.value.y };

  if (head.x < 0 || head.x >= 20 || head.y < 0 || head.y >= 20 || snake.value.some(segment => segment.x === head.x && segment.y === head.y)) {
    pauseGame();
    alert('游戏结束！');
    return;
  }

  snake.value.unshift(head);

  if (head.x === food.value.x && head.y === food.value.y) {
    food.value = generateFood();
  } else {
    snake.value.pop();
  }

  drawGame();
};

const generateFood = () => {
  let newFood;
  do {
    newFood = {
      x: Math.floor(Math.random() * 20),
      y: Math.floor(Math.random() * 20)
    };
  } while (snake.value.some(segment => segment.x === newFood.x && segment.y === newFood.y));
  return newFood;
};

const drawGame = () => {
  ctx.value.clearRect(0, 0, 400, 400);

  // 绘制食物
  ctx.value.fillStyle = 'red';
  ctx.value.fillRect(food.value.x * 20, food.value.y * 20, 20, 20);

  // 绘制蛇
  ctx.value.fillStyle = 'green';
  snake.value.forEach(segment => {
    ctx.value.fillRect(segment.x * 20, segment.y * 20, 20, 20);
  });
};

const handleKeyDown = (event) => {
  if (!isRunning.value) return;
  switch (event.key) {
    case 'ArrowUp':
      if (direction.value.y === 0) direction.value = { x: 0, y: -1 };
      break;
    case 'ArrowDown':
      if (direction.value.y === 0) direction.value = { x: 0, y: 1 };
      break;
    case 'ArrowLeft':
      if (direction.value.x === 0) direction.value = { x: -1, y: 0 };
      break;
    case 'ArrowRight':
      if (direction.value.x === 0) direction.value = { x: 1, y: 0 };
      break;
  }
};
</script>

<style scoped>
.snake-game {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.game-controls {
  margin: 20px 0;
  width: 100%;
  display: flex;
  justify-content: space-between;
  gap: 10px;
  &__btn {
    display: flex;
    gap: 10px;
  }
  .el-select {
    width: 150px;
  }
}

canvas {
  border: 4px solid #E6A23C;
}
</style>